Subject: Re: Producer/Consumer model on Amiga
From: [email-masked] (Doug Walker)
Date: Wed, 19 May 1993 17:09:10 GMT
Newsgroups: comp.sys.amiga.programmer

In article <[email-masked]>, [email-masked] (Scott Maxwell) writes:
|> I guess I'm wondering whether you always have to ReplyMsg() to _every_
|> message you receive via GetMsg() (I always see this done, but I don't
|> know whether it's actually necessary).

No, you don't need to do a ReplyMsg() as long as your second task
knows how to dispose of the message.

Basically, a message is just a block of memory with some fields at
the beginning that allow you to add it to linked lists (the linked
lists are attached to the MsgPort you send it to.)  PutMsg takes your
message and queues that memory block to the target MsgPort.  GetMsg
removes it from that MsgPort and passes a pointer to it to you.

If AmigaDOS or Intuition sends you a message, you MUST REPLY TO IT.
However, if you're simply talking to yourself, as in this case, you
can really do whatever you want.

One example:

   1. Task B allocates MsgPortB using CreatePort(), giving the port a name
   2. Task A uses FindPort() to find MsgPortB
   3. Task A allocates MessageA using AllocMem()
   4. Task A uses PutMsg() to send the MessageA to MsgPortB
   5. Task B uses GetMsg() to receive the message
   6. After using the message, task B uses FreeMem() to free it.
   7. Go back to step 3 and repeat until done

This scenario works fine, but it has one drawback - if you send lots
of messages, you're calling AllocMem and FreeMem a whole heck of a 
lot.  Why do that when you've already got messages allocated?
How about this instead:

   1. Task B allocates MsgPortB using CreatePort(), giving the port a name
   2. Task A allocates MsgPortB using CreatePort(), it's nameless
   3. Task A uses FindPort() to find MsgPortB
   4. Task A calls GetMsg() on MsgPortA.
     4a. If no message is available, Task A allocates one and
         increments a count of allocated messages
     4b. If a message is available, Task A uses it
   5. Task A sets the mn_ReplyPort field to point to MsgPortA
   5. Task A uses PutMsg to send the message
   6. Task B uses GetMsg to receive it
   7. After using the message, task B calls ReplyPort
   8. Go back to step 4 and repeat until done
   9. Until task A's message count is zero, do:
      9a. Task A uses GetMsg on MsgPortA
         9a1. If no message, do a WaitPort()
         9a2. Otherwise free the message and decrement the message count

It's a little more complicated, but much more efficient.

-- 
  *****                    / [email-masked]
 *|_o_o|\\     Doug Walker<  BIX, Portal: djwalker
 *|. o.| ||                \ CompuServe: 71165,2274
  | o  |//     
  ====== 
Any opinions expressed are mine, not those of SAS Institute, Inc.